<?php
namespace App\DataBase;


use App\Core\App;
use App\Exception\SqlException;

class PDO extends \PDO
{

    private static $pdo_statement_class = '';

    private $name;

    public $config;

    private $defaultFetchMode = \PDO::FETCH_BOTH;


    public function __construct($dsn, $username = '', $password = '', $driver_options = [])
    {
        if (!self::$pdo_statement_class) {
            self::$pdo_statement_class = App::getInstance()->getConfig('pdo_statement_class', 'database');
            if (!self::$pdo_statement_class) {
                self::$pdo_statement_class = '\App\DataBase\PDOStatement';
            }
        }

        parent::__construct($dsn, $username, $password, $driver_options);
        $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array(self::$pdo_statement_class, array($this)));
        if (empty($driver_options[PDO::ATTR_ERRMODE])) {
            $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
        }
        $this->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
    }

    /**
     * 执行一条 SQL 语句，并返回受影响的行数
     *
     * @param string $statement 要被预处理和执行的 SQL 语句。
     * @return int
     * @throws SqlException
     */
    public function exec($statement)
    {
        $result = parent::exec($statement);
        $errorInfo = parent::errorInfo();
        if (parent::errorCode() !== '00000') {
            throw new SqlException($this->get_name() . ' | ' . $this->config['dsn'] . ' | ' . $statement . ' | ' . join(' | ', $errorInfo), parent::errorCode());
        }
        return $result;
    }

    /**
     * @param string $statement
     * @param array $driver_options
     * @return PDOStatement
     */
    public function prepare($statement, $driver_options = [])
    {
        $stmt = parent::prepare($statement, $driver_options);
        if ($stmt instanceof \PDOStatement) {
            $stmt->setFetchMode($this->defaultFetchMode);
        }

        return $stmt;
    }

    public function query($statement)
    {
        $stmt = parent::query($statement);

        if ($stmt instanceof \PDOStatement) {
            $stmt->setFetchMode($this->defaultFetchMode);
        }
        return $stmt;
    }

    public function setName($name)
    {
        $this->name = $name;
        $this->config = App::getInstance()->getConfig($name, 'database');
    }

    public function getName()
    {
        return $this->name;
    }

    public function setDefaultFetchMode($mode)
    {
        $this->defaultFetchMode = $mode;
    }
}